/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package orgarqsindex;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import orgarqsindex.btree.BTreeNode;
import orgarqsindex.btree.BTreeNodeKey;

/**
 *
 * @author Fernando Molon Toigo e Dyoni Bertuol
 */
public class FileExplorer {

    private File file;
    private int rowSize;

    public FileExplorer(File file, int rowSize) {
        this.file = file;
        this.rowSize = rowSize;
    }

    public List<RowModel> exhaustiveScan(int columnBeginIndex, int columnSize, String searchParameter) throws FileNotFoundException, IOException {

        searchParameter = searchParameter.trim();
        if (searchParameter.length() > columnSize) {
            return null;
        }

        if (!file.exists() || file.length() == 0) {
            return null;
        }

        List<RowModel> rowsFoundList = new ArrayList<RowModel>();

        RandomAccessFile raf = new RandomAccessFile(file, "r");

        String read;
        byte[] buffer = new byte[columnSize];

        //percorre todas as rows do arquivo
        for (int i = 0; i < file.length(); i += rowSize) {
            raf.seek(i + columnBeginIndex);
            raf.read(buffer);
            read = new String(buffer);
            if (searchParameter.compareToIgnoreCase(read.substring(0, searchParameter.length())) == 0) {
                raf.seek(i);
                byte[] rowFound = new byte[rowSize];
                raf.read(rowFound);
                rowsFoundList.add(new RowModel(new String(rowFound, "ISO-8859-1")));
            }
        }
        raf.close();
        return rowsFoundList;
    }

    public List<RowModel> hashScan(File hashIndexFile, long blockSize, int searchParameter) throws FileNotFoundException, IOException {

        List<RowModel> rowsFoundList = new ArrayList<>();
        RandomAccessFile dataraf = new RandomAccessFile(file, "r");
        RandomAccessFile hashraf = new RandomAccessFile(hashIndexFile, "r");

        int indexRowSize = String.valueOf(file.length() / rowSize).length() + 2;
        long startPosition = searchParameter * blockSize * indexRowSize;

        hashraf.seek(startPosition);
        byte[] buffer = new byte[indexRowSize];
        byte[] rowFound = new byte[rowSize];
        boolean exit = false;
        for (long i = 0; i < blockSize && !exit; i++) {
            hashraf.read(buffer);
            if (buffer[0] == 0) {
                exit = true;
            } else {
                String value = new String(buffer);
                value = value.substring(0, value.length() - 2);
                long pos = Long.valueOf(value);
                dataraf.seek(pos * rowSize);
                dataraf.read(rowFound);
                rowsFoundList.add(new RowModel(new String(rowFound, "ISO-8859-1")));
            }

        }

        return rowsFoundList;

    }

    public List<RowModel> indexScan(File primaryKeyIndexFile, int primaryKeySize, String searchParameter) throws FileNotFoundException, IOException {

        searchParameter = searchParameter.trim();
        if (searchParameter.length() > primaryKeySize) {
            return null;
        }

        if (!file.exists() || file.length() == 0) {
            return null;
        }

        List<RowModel> rowsFoundList = new ArrayList<>();
        RandomAccessFile dataraf = new RandomAccessFile(file, "r");
        RandomAccessFile indexraf = new RandomAccessFile(primaryKeyIndexFile, "r");

        int indexRowSize = primaryKeySize + String.valueOf(file.length() / rowSize).length() + 2;

        long start = 0;
        long end = indexraf.length();

        long middle = 0;
        byte[] buffer = new byte[primaryKeySize];
        boolean found = false;
        while (start != end && !found) {

            middle = ((start + end) / 2);
            middle = (middle / indexRowSize) * indexRowSize;

            indexraf.seek(middle);
            indexraf.read(buffer);

            String readData = new String(buffer, "ISO-8859-1");

            if (readData.compareToIgnoreCase(searchParameter) > 0) {
                end = middle;
            } else if (readData.compareToIgnoreCase(searchParameter) < 0) {
                start = middle + indexRowSize;
            } else {
                found = true;
            }
        }

        if (!found) {
            dataraf.close();
            indexraf.close();
            return rowsFoundList;
        }

        indexraf.seek(middle);
        buffer = new byte[indexRowSize];
        byte[] rowFound = new byte[rowSize];

        indexraf.read(buffer);
        String value = new String(buffer);
        value = value.substring(primaryKeySize, value.length() - 2);
        long pos = Long.valueOf(value);
        dataraf.seek(pos * rowSize);
        dataraf.read(rowFound);
        rowsFoundList.add(new RowModel(new String(rowFound, "ISO-8859-1")));

        dataraf.close();
        indexraf.close();
        return rowsFoundList;

    }
    
    public RowModel bTreeScan(BTreeNode rootNode, long searchParameter) throws FileNotFoundException, IOException{
        RandomAccessFile dataraf = new RandomAccessFile(file, "r");
        
        BTreeNodeKey key = rootNode.find(searchParameter);
        
        if (key == null)
            return null;
        
        byte[] rowFound = new byte[rowSize];
        dataraf.seek(key.getValue() * rowSize);
        dataraf.read(rowFound);
        
        return new RowModel(new String(rowFound, "ISO-8859-1"));
    }
}